#include  <math.h>
#include  <string.h>
#include 	<stdio.h>
#include 	<ctype.h>
#include 	<iiadd.h>
#include 	"iipk.h"
#include 	"orac_compat.h"
#include 	"udt.h"

/* max string length returned by checksum */
#define MAX_ERIS_AT_GET_AT_STRING_LENGTH 400 +  sizeof(short)
#define MAX_ERIS_VARCHAR_TO_NVARCHAR 400 +  sizeof(short)

#ifndef II_NVARCHAR
#define II_NVARCHAR 27
#endif

/*Easy way to start counting the fod_id's*/      		
#define UDF_ERIS_AT_GET_AT_STRING			II_OPSTART
#define OC_TO_DATE										(UDF_ERIS_AT_GET_AT_STRING+1)
#define OC_TO_CHAR          					(OC_TO_DATE+1)


/*Easy way to start counting the fid_id's */
#define UDF_FI_ERIS_AT_GET_AT_STRING   II_FISTART
#define FI_OC_TRANSLATE 							(UDF_FI_ERIS_AT_GET_AT_STRING+1)
#define FI_OC_CTO_DATE      					(FI_OC_TRANSLATE+1)
#define FI_OC_VTO_DATE      					(FI_OC_CTO_DATE+1)
#define FI_OC_CTO_CHAR      					(FI_OC_VTO_DATE+1)
#define FI_OC_VTO_CHAR      					(FI_OC_CTO_CHAR+1)

static const char *oc_months[] =
  {"jan", "feb", "mar", "apr", "may", "jun",
   "jul", "aug", "sep", "oct", "nov", "dec"};
   
static const char *oc_month_nos[] =
  {"01", "02", "03", "04", "05", "06",
   "07", "08", "09", "10", "11", "12"};

II_STATUS   (*Ingres_trace_function)() = 0;

II_STATUS
eris_at_get_at_string(
   II_SCB          *scb,
   II_DATA_VALUE   *p1, /*@table_name*/
   II_DATA_VALUE   *p2,	/*@column_name*/
   II_DATA_VALUE   *p3, /*@value_str*/
   II_DATA_VALUE   *rdv /* return_text  */
){
	char msg[256],msgtemp[10];
	unsigned int true_length1,true_length2,true_length3,data_length1,data_length2,data_length3,temp_length;
	unsigned short offset;
	offset=sizeof(short);
	short usc0,usc1,usc2,usc3,usc4,usc5,usc6;
	int test1,test2;
	int iLen,i;
	rdv->db_prec  = 0;

	
	true_length1 = *(short*)p1->db_data;
	true_length2 = *(short*)p2->db_data;
	true_length3 = *(short*)p3->db_data;
	
	//if out of the range of value, error!
	if(true_length1>40 || true_length2>40 || true_length3>400 ){
						sprintf(msg,"eris_at_get_at_string(): the length of parametres exceeds maximumm permitted (%d) %d %d %d", 40,
										true_length1,true_length2,true_length3);
 						us_error(scb, 0x200011, msg);
						return(II_ERROR);
	};
	
	data_length1 = true_length1*2;
	data_length2 = true_length2*2;
	
	//if p3 is null
	if(true_length3==0){
		
			iLen += true_length1;
			iLen += true_length2;
			iLen +=	5;
	
			*(short *)rdv->db_data=iLen;
			//copy p1
			//memset( rdv->db_data, 0 , sizeof(rdv->db_length));
				for (i	=	0; i < data_length1; i++) {
      		memcpy( rdv->db_data + offset + i ,  p1->db_data + offset + i, 1);
   		};
   		//memcpy( rdv->db_data + offset ,  p1->db_data + offset, data_length1);
   		//.
  			usc1	=	46;
   			usc0	=	0;
   			memcpy( rdv->db_data + offset + data_length1 ,	&usc1, 1);
   			memcpy( rdv->db_data + offset + data_length1 + 1, &usc0 ,1);
   		//copy p2
 		 	//memcpy( rdv->db_data + offset + data_length1 ,  p2->db_data + offset, data_length2);
 		  for (i=0; i < data_length2; i++) {
  		  	memcpy( rdv->db_data + offset + data_length1 + 2 + i ,  p2->db_data + offset + i, 1);
  		};
 		  //=
  			 usc2	=	61;
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 2,	&usc2, 1);
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 3, &usc0, 1);
 		  //""
  		   usc3	=	34;
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 4,	&usc3, 1);
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 5, &usc0, 1);
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6,	&usc3, 1);
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 7, &usc0, 1);
  		//;
  		 	usc4	=	59;
  		 	memcpy( rdv->db_data + offset + data_length1 + data_length2 + 8,	&usc4, 1);
  		 	memcpy( rdv->db_data + offset + data_length1 + data_length2 + 9, &usc0 ,1);  
	}
	else{
		
			data_length3=true_length3*2;	
			//copy p1
			//memset( rdv->db_data, 0 , sizeof(rdv->db_length));
				for (i	=	0; i < data_length1; i++) {
      		memcpy( rdv->db_data + offset + i ,  p1->db_data + offset + i, 1);
   		};
   		//memcpy( rdv->db_data + offset ,  p1->db_data + offset, data_length1);
   		//.
  			usc1	=	46;
   			usc0	=	0;
   			memcpy( rdv->db_data + offset + data_length1 ,	&usc1, 1);
   			memcpy( rdv->db_data + offset + data_length1 + 1, &usc0 ,1);
   		//copy p2
 		 	//memcpy( rdv->db_data + offset + data_length1 ,  p2->db_data + offset, data_length2);
 		  for (i=0; i < data_length2; i++) {
  		  	memcpy( rdv->db_data + offset + data_length1 + 2 + i ,  p2->db_data + offset + i, 1);
  		};
 		  //=
  			 usc2	=	61;
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 2,	&usc2, 1);
  		   memcpy( rdv->db_data + offset + data_length1 + data_length2 + 3, &usc0, 1);
   
   		//"
   		usc3=34;
   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + 4,	&usc3, 1);
   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + 5, &usc0 ,1);
   
   		//copy p3 and replace
   		
   		/*
   		for (i=0; i < data_length3;	i++) {
   			memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6 + i,  p3->db_data + offset + i, 1);
   		};
   		*/
   		i=0;
  		temp_length=0;
   		do{
   			test1 = *(p3->db_data + offset + i);
   			memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6 + temp_length, &test1, 1);
   			i++;
   			temp_length++;
   			
   			test2 = *(p3->db_data + offset + i);
				//memcpy( test2,  (int *)(p3->db_data + offset + i), 1);
				memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6 + temp_length, &test2, 1);
				
				//sprintf(msg,"%d %d",test1,test2);	
 				//us_error(scb, 0x200011, msg);
				//return(II_ERROR);
				
   			if(test1==34&&test2==0){
   					temp_length++;
   		   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6 + temp_length,  &usc3, 1);
   		   		temp_length++;
   		   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + 6 + temp_length,  &usc0, 1);
   		   		//data_length3 = data_length3 + 2;
   		   		true_length3++;
   		 	};
   		 	i++;
   		 	temp_length++;
   		}while(i < data_length3);
   		
   		
   		
   		data_length3 = true_length3 * 2;
   		//"
  		memcpy( rdv->db_data + offset + data_length1 + data_length2 + data_length3 + 6,	&usc3, 1);//+
  		memcpy( rdv->db_data + offset + data_length1 + data_length2 + data_length3 + 7, &usc0 ,1);//+
   		//;
   		usc4=59;	
   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + data_length3 + 8,	&usc4, 1);//+
   		memcpy( rdv->db_data + offset + data_length1 + data_length2 + data_length3 + 9, &usc0 ,1);//+
   		
   		//length rdv
   		iLen += true_length1;
			iLen += true_length2;
			iLen += true_length3;
			iLen +=	5;
			*(short *)rdv->db_data=iLen; 
			
	};
	return(II_OK);			
};/*eris_at_get_at_string(nvachar,nvarchar,nvarchar)*/



/*{
** Name:    oc_tolower	- convert a string to lowercase
**
** Description:
**	Simply convert a given string to lowercase.
*/
static II_STATUS
oc_tolower(char *str, int length) {
  char *curr;

  curr = str;
  while (curr-str < length) {
    if ((*curr>='A') && (*curr<='Z')) {
      *curr = *curr + 'a'-'A';
    }
    curr++;
  }
  return II_OK;
}

/*{
** Name: oc_str_set_len_start() - Sets the length and start pointer of a string.
**
** Description:
**	Accepts a data value, checks the input datatype, obtains 
**      the length and sets the char pointer to the start
**
** Inputs:
**      dv                   Datavalue representing the string
**
** Outputs:
**      str_len              Pointer to integer for length
**	b		     Pointer to pointer to char for start of string
**
**	Returns:
**	    void
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    If the datatype is not a valid string datatype, the char pointer
**          is set to db_data + 2 and the length is set.
**
## History:
##      23-aug-2004 (chen)
##          Created
##      07-sep-2004 (chen)
##          Included checking for datatype C.
[@history_template@]...
**/
void
oc_str_set_len_start(II_DATA_VALUE *dv, i4 *str_len, char **b) {
    if ((dv->db_datatype == II_CHAR)
	|| (dv->db_datatype == II_C)) {
      *str_len = dv->db_length; /* The input string length */
      *b = dv->db_data;
    }
    else {
      II_VLEN   *vlen;
      short     s;
      vlen = (II_VLEN *)dv->db_data;
      I2ASSIGN_MACRO(vlen->vlen_length, s);
      *str_len = s;               /* The input string length */
      *b = ((char *)dv->db_data + 2);
    }
}

/*{
** Name:    oc_find_month_no	- find the number of a month
**
** Description:
**	Finds the month number given MON.
**      eg: oc_find_month_no("oct", &month_no)
**      puts 10 in month_no
*/
static II_STATUS
oc_find_month_no(char *month, int *month_no) {
  int i = 0;

  for (i=0; i<12; i++) {
    if (!strncmp(month, oc_months[i], 3)) {
      *month_no = (i+1);
      break;
    }
  }
  if (i == 12)
    return II_ERROR;
  return II_OK;
}

/*{
** Name:    oc_copy_number	- copy number string left padding it with zeros
**
** Description:
**	This routine takes two strings and copies the number in the first
**	string into the second padding it with zeros till it is of the specified
**      length. The deficit is the number of zeroes that had to be padded.
**
**  Inputs:
**	from				The pointer to the number string
**	to  			        The string to fill in
**	length 			        The length of the output string
**	deficit			        The number of digits less or the number
**				        of padded zeros
**
**  Outputs:
**	to, deficit			Filled with the aforementioned
**					information.
*/
static II_STATUS
oc_copy_number(char *from, char *to, int length, int *deficit) {
  int len = 0;
  int less = 0;
  int i = 0;
  char *curr;

  curr = from;

  if ((*curr<'0') || (*curr>'9'))
    return II_ERROR;

  while ((*curr>='0') && (*curr<='9') && (len<length)) {
    len++;
    curr++;
  }

  less = length - len;

  for (i=0; i<less; i++)
    byte_copy("0", 1, to+i);

  byte_copy(from, len, to+less);

  *deficit = less;
  return II_OK;
}

   
/*{
** Name: oc_to_date() - Converts the string to date string, given the format.
**
** Description:
**	Converts the string to date, given the date format string.
**      The output string will be of format dd-mmm-yyyy
**      Valid format tokens:
**          - / :
**          mon, yyyy, dd, mm, hh24, mi, ss
**      Examples:
**          mon-yyyy
**          dd-mon-yyyy
**          yyyymm
**          yyyymmdd
**          dd/mm/yyyy
**          syyyy-mm-dd
**          dd-mon-yyyy hh24:mi:ss
**          dd-mm-yyyy
**          syyyy-mm-dd hh24:mi:ss
**
** Inputs:
**      scb                      Scb
**      dv_str                   Datavalue representing the date string
**      dv_format                Datavalue representing the date format string
**	dv_result		 Datavalue in which to place the result
**
** Outputs:
**      *dv_result.db_data       Varchar result is placed here.
**                .db_datatype   Should contain II_VARCHAR
**
**	Returns:
**	    II_STATUS
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
## History:
##      25-aug-2004 (chen)
##          Created
[@history_template@]...
**/
II_STATUS
#ifdef __STDC__
oc_to_date(II_SCB       *scb ,
        II_DATA_VALUE   *dv_str ,
        II_DATA_VALUE   *dv_format ,
        II_DATA_VALUE   *dv_result )
#else
oc_to_date(scb, dv_str, dv_format, dv_result)
II_SCB          *scb;
II_DATA_VALUE   *dv_str;
II_DATA_VALUE   *dv_format;
II_DATA_VALUE   *dv_result;
#endif
{
  II_STATUS			result = II_ERROR;
  char			        *b_str;
  char			        *b_format;
  char			        *b_out;
  char			        *b1;
  char			        *b2;
  char			        *msg;
  int			        str_length;
  int			        format_length;
  int			        check_length;
  int                           fdiff = 0;
  int                           deficit = 0;

  if (dv_result->db_data) {
    result = II_OK;

    /* Finding out the result length */
    b_out = dv_result->db_data;
    check_length = dv_result->db_length;

    /* If the type is varchar, decrease result length by 2 */
    if (dv_result->db_datatype != II_CHAR) {
      check_length -= 2;
      b_out += sizeof(short);
    }

    /* 
     * Checking the input datatype, obtaining the length and setting the start
     */
    oc_str_set_len_start(dv_str, &str_length, &b_str);
    oc_str_set_len_start(dv_format, &format_length, &b_format);
    b1 = b_str;
    b2 = b_format;
    byte_copy((char *)"01-jan-2004 00:00:00", 20, b_out);
    oc_tolower(b_format, format_length);

    while (b2-b_format < format_length-1) {

      b1 = b_str+(b2-b_format)-fdiff;

      if (*b1==' ') {
	fdiff--;
      }
      else if (*b2==' ') {
	fdiff++;
	b2++;
      }
      else if (((*b1=='/') && (*b2=='/'))
	       || ((*b1=='-') && (*b2=='-'))
	       || ((*b1=='.') && (*b2=='.'))
	       || ((*b1==':') && (*b2==':'))) {
	b2++;
      }
      else if (!strncmp(b2, "dd", 2)) {
	oc_copy_number(b1, b_out+0, 2, &deficit);
	b2+=2;
	fdiff += deficit;
      }
      else if (!strncmp(b2, "mm", 2)) {
	int month_no = atoi(b1)-1;
	oc_copy_number(b1, b_out+3, 2, &deficit);
	if (month_no>=0 && month_no<12) {
	  byte_copy((char *)oc_months[month_no], 3, b_out+3);
	}
	else {
	  msg = "Oc_to_date: Invalid date";
	  result = II_ERROR; break;
	}
	fdiff += deficit;
	b2 += 2;
      }
      else if (!strncmp(b2, "mon", 3)) {
	byte_copy(b1, 3, b_out+3);
	b2 += 3;
      }
      else if (!strncmp(b2, "yyyy", 4)) {
	oc_copy_number(b1, b_out+7, 4, &deficit);
	b2 += 4;
	fdiff += deficit;
      }
      else if (!strncmp(b2, "yy", 2)) {
	oc_copy_number(b1, b_out+9, 2, &deficit);
	b2+=2;
	fdiff += deficit;
      }
      else if (!strncmp(b2, "hh24", 2)) {
	oc_copy_number(b1, b_out+12, 2, &deficit);
	b2 += 4;
	fdiff += (deficit+2);
      }
      else if (!strncmp(b2, "mi", 2)) {
	oc_copy_number(b1, b_out+15, 2, &deficit);
	b2+=2;
	fdiff += deficit;
      }
      else if (!strncmp(b2, "ss", 2)) {
	oc_copy_number(b1, b_out+18, 2, &deficit);
	b2+=2;
	fdiff += deficit;
      }
      else if (!strncmp(b2, "syyyy", 5)) {
	if ((*b1=='+') || (*b1=='-')) {
	}
	else
	  fdiff = 1;
	b2++;
      }
      else {
	msg = "Oc_to_date: Invalid date format";
	result = II_ERROR; break;
	break;
      }
    }

    if (dv_result->db_datatype != II_CHAR) {
      short final_length;
      final_length = 20;
      I2ASSIGN_MACRO(final_length, *dv_result->db_data);
    }
  }
  else {
    msg = "Oc_to_date: Invalid input";
  }

  if (result)
    us_error(scb, 0x200011, msg);

  return (result);
}

/*{
** Name: oc_to_char() - Converts the date to date string, given the format.
**
** Description:
**	Converts the date to date string, given the date format string.
**      The input string will be of format dd-mmm-yyyy [hh:mm[:ss]]
**      Valid format tokens:
**          - / :
**          mon, yyyy, dd, mm, hh24, mi, ss
**      Examples:
**          mon-yyyy
**          dd-mon-yyyy
**          yyyymm
**          yyyymmdd
**          dd/mm/yyyy
**          syyyy-mm-dd
**          dd-mon-yyyy hh24:mi:ss
**          dd-mm-yyyy
**          syyyy-mm-dd hh24:mi:ss
**
** Inputs:
**      scb                      Scb
**      dv_date                  Datavalue representing the date
**      dv_format                Datavalue representing the date format string
**	dv_result		 Datavalue in which to place the result
**
** Outputs:
**      *dv_result.db_data       Varchar or char result is placed here.
**                .db_datatype   Should contain II_VARCHAR or II_CHAR
**
**	Returns:
**	    II_STATUS
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
## History:
##      27-aug-2004 (chen)
##          Created
[@history_template@]...
**/
II_STATUS
#ifdef __STDC__
oc_to_char(II_SCB       *scb ,
        II_DATA_VALUE   *dv_date ,
        II_DATA_VALUE   *dv_format ,
        II_DATA_VALUE   *dv_result )
#else
oc_to_char(scb, dv_date, dv_format, dv_result)
II_SCB          *scb;
II_DATA_VALUE   *dv_date;
II_DATA_VALUE   *dv_format;
II_DATA_VALUE   *dv_result;
#endif
{
  II_STATUS			result = II_ERROR;
  char			        *b_date;
  char			        *b_format;
  char			        *b_out;
  char			        *b1;
  char			        *b2;
  char			        *msg;
  int			        date_length;
  int			        format_length;
  int			        check_length;
  int                           fdiff = 0;

  if (dv_result->db_data) {
    result = II_OK;

    /* Finding out the result length */
    b_out = dv_result->db_data;
    check_length = dv_result->db_length;

    /* If the type is varchar, decrease result length by 2 */
    if (dv_result->db_datatype != II_CHAR) {
      check_length -= 2;
      b_out += sizeof(short);
    }

    /* 
     * Checking the input datatype, obtaining the length and setting the start
     */
    oc_str_set_len_start(dv_date, &date_length, &b_date);
    oc_str_set_len_start(dv_format, &format_length, &b_format);
    b1 = b_out;
    b2 = b_format;

    oc_tolower(b_format, format_length);

    while (b2-b_format < format_length-1) {
      b1 = b_out+(b2-b_format)-fdiff;

      if ((*b2=='/') || (*b2=='-') || (*b2==':') 
	  || (*b2==' ') || (*b2=='.')) {
	*b1 = *b2++;
      }
      else if (!strncmp(b2, "dd", 2)) {
	byte_copy(b_date, 2, b1);
	b2 += 2;
      }
      else if (!strncmp(b2, "mm", 2)) {
	int month_no = 0;
	if (oc_find_month_no(b_date+3, &month_no) == II_ERROR) {
	  msg = "Oc_to_char: Invalid date";
	  result = II_ERROR;
	}
	else {
	  byte_copy((char *)oc_month_nos[month_no-1], 2, b1);
	}      
	b2 += 2;
      }
      else if (!strncmp(b2, "mon", 3)) {
	byte_copy(b_date+3, 3, b1);
	b2 += 3;
      }
      else if (!strncmp(b2, "yyyy", 4)) {
	byte_copy(b_date+7, 4, b1);
	b2 += 4;
      }
      else if (!strncmp(b2, "yy", 2)) {
	byte_copy(b_date+9, 2, b1);
	b2 += 2;
      }
      else if (!strncmp(b2, "hh24", 2)) {
	if (atoi(b_date+12)==0)
	  byte_copy("00", 2, b1);
	else
	  byte_copy(b_date+12, 2, b1);
	b2 += 4;
	fdiff += 2;
      }
      else if (!strncmp(b2, "mi", 2)) {
	if (atoi(b_date+15)==0)
	  byte_copy("00", 2, b1);
	else
	  byte_copy(b_date+15, 2, b1);
	b2 += 2;
      }
      else if (!strncmp(b2, "ss", 2)) {
	if (atoi(b_date+18)==0)
	  byte_copy("00", 2, b1);
	else
	  byte_copy(b_date+18, 2, b1);
	b2 += 2;
      }
      else if (!strncmp(b2, "syyyy", 5)) {
	*b1=='+';
	b2++;
      }
      else {
	msg = "Oc_to_char: Invalid date format";
	result = II_ERROR;
	break;
      }
    }

    b1 = b_out+(b2-b_format)-fdiff;
    if (dv_result->db_datatype != II_CHAR) {
      short final_length;
      final_length = (b1-b_out);
      I2ASSIGN_MACRO(final_length, *dv_result->db_data);
    }
    else {
      blank_pad(b1, check_length-(b1-b_out));
    }
  }
  else {
    msg = "Oc_to_char: Invalid input";
  }

  if (result)
    us_error(scb, 0x200012, msg);

  return (result);
}




/* Need arrays of 2-byte integers to hold the function argument datatypes
** Here are some examples...
*/

static II_DT_ID  UD_3_NVARCHAR[]	 = {II_NVARCHAR,II_NVARCHAR,II_NVARCHAR};
static	II_DT_ID oc_2char_parms[] = { II_CHAR, II_CHAR };
static	II_DT_ID oc_2varchar_parms[] = { II_VARCHAR, II_VARCHAR };

	  	     	
static IIADD_FO_DFN Function_Definitions[]={
   {
   	II_O_OPERATION,   /*fod_object_type*/
   	{"eris_at_get_at_string"}, /*fod_name*/
   UDF_ERIS_AT_GET_AT_STRING, /*fod_id*/
   II_NORMAL         /*fod_type*/
   },/* eris_at_get_at_string(nvarchar,nvarchar,nvarchar) */
   	{ II_O_OPERATION, { "to_date"},
	    OC_TO_DATE, II_NORMAL },
	{ II_O_OPERATION, { "to_char"},
	    OC_TO_CHAR, II_NORMAL }

};


static IIADD_FI_DFN Function_Instances[] = {
    {
    II_O_FUNCTION_INSTANCE,       /* fid_object_type */
    UDF_FI_ERIS_AT_GET_AT_STRING, /* fid_id*/
    II_NO_FI,                     /* fid_cmplmnt*/
    UDF_ERIS_AT_GET_AT_STRING,    /* fid_opid=fod_id from function definition */
    II_NORMAL,                    /* fid_optype */
    II_FID_F0_NOFLAGS,            /* fid_attributes*/
    0,                            /* fid_wslength*/
    3,                            /* fid_numargs*/
    UD_3_NVARCHAR,               	/* fid_args, a pointer to an array of datatypes*/
    II_NVARCHAR,                   /* fid_result, result is an integer*/
    II_RES_FIXED,                 /* fid_rltype*/
    MAX_ERIS_AT_GET_AT_STRING_LENGTH,         /* fid_rlength */
    0,                            /* fid_rprec */
    eris_at_get_at_string,        /* fid_routine */
    0       											/* lenspec_routine */
    }, /*eris_at_get_at_string(nvarchar,nvarchar,nvarchar)*/
    { II_O_FUNCTION_INSTANCE, FI_OC_CTO_DATE, II_NO_FI,
		OC_TO_DATE, II_NORMAL, II_FID_F0_NOFLAGS, 0,
	    2, oc_2char_parms, II_CHAR, II_RES_FIXED, 20,
	    0, oc_to_date , 0 },/*to_date*/
	   { II_O_FUNCTION_INSTANCE, FI_OC_VTO_DATE, II_NO_FI,
		OC_TO_DATE, II_NORMAL, II_FID_F0_NOFLAGS, 0,
	    2, oc_2varchar_parms, II_VARCHAR, II_RES_FIXED, 22,
	    0, oc_to_date , 0 },/*to_date*/

	{ II_O_FUNCTION_INSTANCE, FI_OC_CTO_CHAR, II_NO_FI,
		OC_TO_CHAR, II_NORMAL, II_FID_F0_NOFLAGS, 0,
	    2, oc_2char_parms, II_CHAR, II_RES_SECOND, II_LEN_UNKNOWN,
	    0, oc_to_char , 0 },/*to_char*/

	{ II_O_FUNCTION_INSTANCE, FI_OC_VTO_CHAR, II_NO_FI,
		OC_TO_CHAR, II_NORMAL, II_FID_F0_NOFLAGS, 0,
	    2, oc_2varchar_parms, II_VARCHAR, II_RES_SECOND, II_LEN_UNKNOWN,
	    0, oc_to_char , 0 }/*to_char*/
	   
};

/*{
** Name: IIUDADT_REGISTER   - Add the datatype to the server
**
** Description:
**      This routine is called by the DBMS server to add obtain information to
**  add the datatype to the server.  It simply fills in the provided
**  structure and returns.
**
** Inputs:
**      ui_block                        Pointer to user information block.
**  callback_block          Pointer to an II_CALLBACKS structure
**                  which contains information about INGRES
**                  callbacks which are available.
**
**                  Note that after this routine returns
**                  the address of this block is no longer
**                  valid.  Therefore, this routine must
**                  copy the contents in which it is
**                  interested before returning.
**
** Outputs:
**      *ui_block                       User information block
**
**  Returns:
**      II_STATUS
**  Exceptions:
**      none
**
** Side Effects:
**      none
**
## History:
##      02-Mar-1989 (fred)
##          Created.
##  20-Feb-2001 ( fanra01, gupsh01)
##      Added new ifdef #NEED_THIS, the udadt_register
##      is now moved to nvarchar.c
##
*/

static  IIADD_DEFINITION    register_block =
{
    (IIADD_DEFINITION *) 0,
  (IIADD_DEFINITION *) 0,
    sizeof(IIADD_DEFINITION),
   IIADD_DFN2_TYPE,
    0,
    0,
    0,
    0,
    IIADD_INCONSISTENT, /* Ignore the current datatypes known by the recovery
                    system */
    2,  /* Major id */
    0,  /* minor id */
    33,  /*MAS*/
   "Compatibility UDFs add (checksum)and (rand_seq_gen)",  /*MAS*/
    IIADD_T_FAIL_MASK | IIADD_T_LOG_MASK,
    0,     /* set in register function - MAS */
    0,  /* set to zero as there are no types defined MAS */
    0,  /* set to zero as there are no types defined MAS */
   (sizeof(Function_Definitions)/sizeof(IIADD_FO_DFN)),
    Function_Definitions,
  (sizeof(Function_Instances)/sizeof(IIADD_FI_DFN)),
   Function_Instances
};

II_STATUS
IIudadt_register(IIADD_DEFINITION  **ui_block_ptr ,
                 II_CALLBACKS       *callback_block )
{
    
    register_block.add_count = register_block.add_dt_cnt +
            register_block.add_fo_cnt +
            register_block.add_fi_cnt;
    *ui_block_ptr = &register_block;
 
    /*
    ** Note that after this call, the call back block address will
    ** no longer be valid (the function addresses will, but the block
    ** address itself will not).  Therefore, it is necessary to
   ** copy the values in which we are interested before returning.
   */   
     
  
    if (callback_block && callback_block->ii_cb_version >= II_CB_V1)
    {
    Ingres_trace_function = callback_block->ii_cb_trace;
    if (callback_block->ii_cb_version >= II_CB_V2)
    {
        usc_lo_handler = callback_block->ii_lo_handler_fcn;
        usc_lo_filter = callback_block->ii_filter_fcn;
        usc_setup_workspace = callback_block->ii_init_filter_fcn;
        usc_error = callback_block->ii_error_fcn;
    }
    }
    else
    {
    Ingres_trace_function = 0;
 }
    return(II_OK);
}
